package com.accounting.client.frontend.order;

import java.util.Date;

import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.common.CurrencyBox;
import com.accounting.client.frontend.common.CustomerSelector;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.Courier;
import com.accounting.client.remote.enumeration.Currency;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.Customer;
import com.accounting.client.remote.obj.OrderItem;
import com.accounting.client.remote.obj.Product;
import com.accounting.client.remote.obj.Stock;
import com.accounting.client.remote.transfer.CreateOrderRequest;
import com.accounting.client.remote.transfer.SearchStockRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;

import corelib.client.CollectionUtil;
import corelib.client.Util;
import corelib.client.delegate.Action;
import corelib.client.delegate.CompleteCallback;
import corelib.client.delegate.DataCallback;
import corelib.client.delegate.Func1;
import corelib.client.linq.Linq;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.search.PagingRequest;
import corelib.client.search.PagingResult;
import corelib.client.ui.LazyWidget;
import corelib.client.ui.SimpleMask;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.ImageProvider;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.button.Button;
import corelib.client.ui.widget.dialog.SimpleDialog;
import corelib.client.ui.widget.dialog.SimpleLargeDialogHandler;
import corelib.client.ui.widget.form.DateBox;
import corelib.client.ui.widget.form.DecimalBox;
import corelib.client.ui.widget.form.SelectField;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.form.TextAreaField;
import corelib.client.ui.widget.form.TextField;
import corelib.client.ui.widget.form.fomatters.ValueFormatter;
import corelib.client.ui.widget.layout.RelativeColumn;
import corelib.client.ui.widget.layout.RelativeLayout;
import corelib.client.ui.widget.layout.RelativeRow;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;
import corelib.client.ui.widget.panel.SimpleLayoutPanel;
import corelib.client.ui.widget.panel.SimpleListPanel;
import corelib.client.ui.widget.toolbar.SimpleRibbon;

public class CreateOrderHandler extends SimpleLargeDialogHandler {
	
	private SelectField<Product>       productField;
	private SimpleListPanel<Stock>   listPanel;
	private SelectField<StockLocation> locationField;
	private DateBox 				 orderDateField;
	private DecimalBox 				 currentRateField;
	private SimpleRibbon 			 toolBar;
	
	private OrderItemsPanel   orderItemsPanel;
	private OrderPackagePanel orderPackagePanel = null;
	
	private Action submitAction;
	
	public CreateOrderHandler(Action action){
		this.submitAction = action;
	}
	
	@Override
	public Widget getContentPanel() {
		toolBar = createToolBar();
		SimpleLayoutPanel layout = new SimpleLayoutPanel();
		SplitLayoutPanel contentPanel = createContentPanel();
		layout.add(toolBar);
		layout.add(contentPanel);
		layout.setWidgetTopHeight(toolBar, 0, Unit.PX, 32, Unit.PX);
		layout.setWidgetTopBottom(contentPanel, 44, Unit.PX, 0, Unit.PX);
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				search(Util.EMPTY_STRING);
			}
		}, 500);
		
		return layout;
	}

	protected SimpleRibbon createToolBar() {
		this.toolBar = new SimpleRibbon();
		this.toolBar.getElement().getStyle().setPaddingTop(15, Unit.PX);
		orderDateField = new DateBox();
		orderDateField.setDate(new Date());
		
		currentRateField = new DecimalBox();
		currentRateField.getElement().getStyle().setMarginLeft(10, Unit.PX);
		
		currentRateField.setDouble(ApplicationContext.getCurrentRate());
		productField = new SelectField<Product>(new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				search(Util.EMPTY_STRING);
			}
		});
		
		productField.setWidth(200);
		productField.setNullable(true);
		productField.getElement().getStyle().setMarginLeft(10, Unit.PX);
		productField.setOptionFormatter("请选择产品", new ValueFormatter<Product>(){
			@Override
			public String format(Product value) {
				return value.getCName();
			}
		});
		
		locationField = new SelectField<StockLocation>(StockLocation.All, new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				search(Util.EMPTY_STRING);
			}
		});
		locationField.setNullable(true);
		locationField.setOptionFormatter("请选择库存位置", new ValueFormatter<StockLocation>(){
			@Override
			public String format(StockLocation value) {
				return value.getCname();
			}
		});
		locationField.getElement().getStyle().setMarginLeft(10, Unit.PX);
		locationField.setWidth(200);
		
		Button submitBtn = new Button("递交交易", CommonResources.INSTANCE.accept16(), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				createOrder();
			}
		});
		submitBtn.setWidth(80);
		submitBtn.getElement().getStyle().setMarginLeft(5, Unit.PX);
		Button clearAllBtn = new Button("清除", BoxResources.INSTANCE.clear16(), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				orderItemsPanel.clear();
				if (orderPackagePanel != null){
					orderPackagePanel.reset();
				}
			}
		});
		clearAllBtn.getElement().getStyle().setMarginLeft(10, Unit.PX);
		Button close = new Button("关闭", BoxResources.INSTANCE.delete16(), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				closeDialog();
			}
		});
		
		SimpleLabel label = new SimpleLabel("当前汇率").setBold(true);
		label.getElement().getStyle().setMarginLeft(10, Unit.PX);
		
		SimpleLabel label2 = new SimpleLabel("销售日期").setBold(true);
		label.getElement().getStyle().setMarginLeft(10, Unit.PX);
		
		RelativeRow row = new RelativeRow();
		row.add(productField,260)
		   .addSpace(8)
		   .add(locationField,200)
		   .addSpace(8)
		   .add(label)
		   .add(currentRateField, 100)
		   .addSpace(8)
		   .add(label2)
		   .addSpace(8)
		   .add(orderDateField, 100)
		   .addSpace(8)
		   .add(clearAllBtn)
		   .addSpace(8)
		   .add(submitBtn);
		   
		toolBar.addWidget(row.getPanel());
		toolBar.addWidget(close, Style.Float.RIGHT);
		return toolBar;
	}
	
	protected SplitLayoutPanel createContentPanel() {
		SplitLayoutPanel contentPanel = new SplitLayoutPanel();
		contentPanel.getElement().getStyle().setBorderColor("#eee");
		contentPanel.getElement().getStyle().setBorderWidth(1, Unit.PX);
		
		orderItemsPanel = new OrderItemsPanel();
		orderItemsPanel.setRowSpacing(20);
		listPanel = new SimpleListPanel<Stock>(new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				Stock info = listPanel.getSelectedOption();
				if (info == null){
					return ;
				}
				
				if (info.getStock() == 0) {
					SimpleMessageBox.error("库存不足", "此商品已经卖出， 请到购买库存管理页面增加库存.", CompleteCallback.Nil);
					return;
				}
				
				OrderItem item = new OrderItem();
				item.setStockId(info.getId());
				item.setCost(info.getPrice());
				item.setCostCurrency(info.getPriceCurrency());
				item.setProductName(info.getProductName());
				item.setPriceCurrency(Currency.RMB.getName());
				item.setCount(info.getStock());
				item.setProductId(info.getProductId());
				item.setPostage(info.getPostage());
				item.setLocation(info.getLocation());
				item.setCurrencyRate(ApplicationContext.getCurrentRate());
				orderItemsPanel.addOrderRow(new OrderItemRow(item, orderItemsPanel));
			}
		});
		
		listPanel.setOptionFormatter(new ValueFormatter<Stock>(){
			@Override
			public String format(Stock value) {
				return value.getProductName() +"( "+ value.getStock() +" )";
			}
		});
		
		listPanel.setIconProvider(new ImageProvider<Stock>(){
			@Override
			public AbstractImagePrototype getImage(Stock value) {
				return AbstractImagePrototype.create(BoxResources.INSTANCE.cube16());
			}
		});
		listPanel.getElement().getStyle().setProperty("borderRight","1px sold #bbb");
		
		SplitLayoutPanel panel = createSummaryPanel();
		panel.getElement().getStyle().setProperty("borderLeft","1px sold #bbb");
		
		contentPanel.addWest(listPanel, 260);
		contentPanel.add(panel);
		return contentPanel;
	}
	
	protected SplitLayoutPanel createSummaryPanel(){
		SplitLayoutPanel panel = new SplitLayoutPanel();
		panel.getElement().getStyle().setPadding(20, Unit.PX);
		ScrollPanel scroll = new ScrollPanel();
		scroll.setWidth("95%");
		scroll.getElement().getStyle().setPadding(20, Unit.PX);
		scroll.add(orderItemsPanel.getPanel());
		panel.addNorth(scroll,150);
		panel.add(orderPackagePanel = new OrderPackagePanel());
		return panel;
	}
	
	@Override
	public void onShowing() {
		super.onShowing();
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				PagingRequest request = new PagingRequest();
				request.setOffset(0);
				request.setLimit(100);
				request.setKeyword(Util.EMPTY_STRING);
				Services.ProductService.ListProductsByKeyword(SessionManager.getPassport(), request,
					new AsyncCallback<PagingResult<Product>>(){
						@Override
						public void onFailure(Throwable caught) {
							ErrorHandler.handleServiceError(caught);
						}
						
						@Override
						public void onSuccess(PagingResult<Product> result) {
							productField.setOptions(result.getData(), false);
						}
					}
				);
			}
		},400);
	}

	private void search(String keyword) {
		
		String passport  = SessionManager.getPassport();
		String productId = productField.getSelectedOption() == null 
						   ? null 
						   : productField.getSelectedOption().getProductId();
		
		Integer location = locationField.getSelectedOption() == null 
						 ? null
						 : locationField.getSelectedOption().getLocation();
		
		SearchStockRequest request = new SearchStockRequest();
		request.setOffset(0);
		request.setLimit(1000);
		request.setProductId(productId);
		request.setLocation(location);
		
		SimpleModal.show("搜索中...");
		Services.ProductService.SearchStocks(passport, request,
			new AsyncCallback<PagingResult<Stock>>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(PagingResult<Stock> result) {
					SimpleModal.hide();
					listPanel.setOptions(result.getData());
				}
			}
		);
	}
	
	private void createOrder() {
		if (currentRateField.getDouble() == null){
			currentRateField.markError("请输入当前的汇率");
			return;
		}
		
		if (CollectionUtil.isEmpty(orderItemsPanel.getOrderItem())){
			SimpleMessageBox.error("错误", "必须选择要销售产品.", CompleteCallback.Nil);
			return;
		}
		
		for (OrderItemRow row : orderItemsPanel.getOrderItemIndex()) {
			if (row.validate() == Boolean.FALSE){
				return;
			}
		}
		
		int count = Linq.sumi(orderItemsPanel.getOrderItem(), new Func1<OrderItem, Integer>(){
			@Override
			public Integer run(OrderItem param) {
				return param.getCount();
			}
		});
		
		if (count > 10){
			SimpleMessageBox.error("产品数量过多", "产品数量过多，奶粉类产品最多只能6瓶子，其他产品是10.",  CompleteCallback.Nil);
			return;
		}
		
		if (orderPackagePanel == null || Util.isNullOrEmpty(orderPackagePanel.getCustomerId())){
			SimpleMessageBox.error("错误", "必须选择收件人.",  CompleteCallback.Nil);
			return;
		}
		
		if (orderPackagePanel.getCourierField().getSelectedOption() == null){
			orderPackagePanel.getCourierField().markError("快递不能为空.");
			return;
		}
		
		if (orderPackagePanel.getCourierField().getSelectedOption() != Courier.Other 
		 && orderPackagePanel.getPostage() == 0.0){
			orderPackagePanel.getPostageField().markError("当快递不为其他时邮费不能为零.");
			return;
		}
		
		if (Util.isNullOrEmpty(orderPackagePanel.getAddress())){
			orderPackagePanel.getAddressField().markError("收件人地址不能为空.");
			return;
		}
		if (Util.isNullOrEmpty(orderPackagePanel.getPhoneNumber())){
			orderPackagePanel.getPhoneField().markError("收件人电话号码不能为空.");
			return;
		}
		
		CreateOrderRequest request = new CreateOrderRequest();
		request.setOrderItems(orderItemsPanel.getOrderItem());
		request.setCustomerId(orderPackagePanel.getCustomerId());
		request.setPhoneNumber(orderPackagePanel.getPhoneNumber());
		request.setShippingAddress(orderPackagePanel.getAddress());
		request.setCourierId(orderPackagePanel.getCourierId());
		request.setTrackingId(orderPackagePanel.getTrackingId());
		request.setCurrentRate(currentRateField.getDouble());
		request.setDateOrdered(orderDateField.getDate());
		request.setOrderPostage(orderPackagePanel.getPostage());
		request.setOrderPostageCurrency(Currency.AUD.getName());
		
		SimpleMask.mask(getDialog(), "创建中...");
		Services.OrderService.CreateOrder(SessionManager.getPassport(), request, new AsyncCallback<Boolean>() {
				@Override
				public void onFailure(Throwable caught) {
					SimpleMask.unmask(getDialog());
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(Boolean result) {
					SimpleMask.unmask(getDialog());
					if (result == Boolean.TRUE) {
						closeDialog();
						if (submitAction != null){
							submitAction.run();
						}
					}
				}
		});
	}
	
	public class OrderPackagePanel extends LazyWidget<FlowPanel> {
		
		private Customer customer = null;
		
		private TextAreaField  addressField;
		private CurrencyBox  postageField;
		private TextField trackingIdField;
		private TextField emailField;
		private TextField phoneField;
		private TextField nameField;
		private SelectField<Courier> courierField;
		
		@Override
		protected FlowPanel createWidget() {
			courierField = new SelectField<Courier>(Courier.All);
			courierField.setNullable(true);
			courierField.setOptionFormatter("请选择快递", new ValueFormatter<Courier>() {
				@Override
				public String format(Courier value) {
					return value.getCName();
				}
			});
			
			trackingIdField = new TextField();
			postageField    = new CurrencyBox();
			addressField    = new TextAreaField();
			addressField.setHeight(150);
			emailField = new TextField();
			phoneField = new TextField();
			nameField  = new TextField();
			
			Button button = new Button("点击选择收件人", BoxResources.INSTANCE.add16(),new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					SimpleDialog.show(new CustomerSelector(new DataCallback<Customer>() {
						@Override
						public void onCompleted(Customer customerInfo) {
							if (customerInfo != null) {
								customer = customerInfo;
								sync(customerInfo);
							}
						}
					}));
				}
			});
			
			FlowPanel panel = new FlowPanel();
			panel.getElement().getStyle().setPadding(20, Unit.PX);
			
			int lw = 80;
			int fw = 150;
			
			RelativeColumn col = new RelativeColumn();
			col.setRowSpacing(20);
			
			col.addRow()
			   .add(new SimpleLabel("快递").setBold(true), courierField, RelativeLayout.createLeftLabel(fw, lw))
			   .addSpace(12)
			   .add(new SimpleLabel("邮费").setBold(true), postageField, RelativeLayout.createLeftLabel(fw, lw))
			   .addSpace(12)
			   .add(new SimpleLabel("快递查询号").setBold(true), trackingIdField, RelativeLayout.createLeftLabel(fw, lw));
			
			col.addRow()
			   .add(new SimpleLabel("姓名").setBold(true),   nameField,  RelativeLayout.createLeftLabel(fw, lw))
			   .addSpace(12)			   
			   .add(new SimpleLabel("电话号码").setBold(true), phoneField, RelativeLayout.createLeftLabel(fw, lw))
			   .addSpace(12)
			   .add(new SimpleLabel("电子邮件").setBold(true), emailField,   RelativeLayout.createLeftLabel(fw, lw));
			
			col.addRow().add(new SimpleLabel("收件人地址").setBold(true), lw);
			col.addRow().add(addressField, (fw + lw) * 3);
			col.addRow().add(button, 150);
			
			panel.add(col.getPanel());
			return panel;
		}
		
		public void sync(Customer customerInfo){
			addressField.setValue(customerInfo.getAddress1());
			emailField.setText(customerInfo.getEmail1(),false);
			phoneField.setText(customerInfo.getPhoneNumber1(),false);
			nameField.setText(customerInfo.getCName(),false);
		}
		
		public Customer getCustomer() {
			return customer;
		}

		public TextAreaField getAddressField() {
			return addressField;
		}

		public SelectField<Courier> getCourierField() {
			return courierField;
		}

		public CurrencyBox getPostageField() {
			return postageField;
		}

		public TextField getTrackingIdField() {
			return trackingIdField;
		}

		public TextField getPhoneField() {
			return phoneField;
		}

		public TextField getNameField() {
			return nameField;
		}

		public String getCustomerId() {
			return customer == null ? Util.EMPTY_STRING : customer.getId();
		}
		
		public String getCustomerName(){
			return customer == null ? Util.EMPTY_STRING : customer.getName();
		}
		
		public String getAddress() {
			return addressField.getTrimmedValueOrEmptyString();
		}

		public int getCourierId() {
			return courierField.getSelectedOption().getCode();
		}

		public String getEmailField() {
			return emailField.getTrimmedText();
		}

		public String getPhoneNumber() {
			return phoneField.getTrimmedText();
		}
		
		public double getPostage(){
			return postageField.getDouble(0.0);
		}
		
		public String getTrackingId(){
			return trackingIdField.getTrimmedText();
		}
		
		public void reset() {
			customer = null;
			courierField.setSelectedOption(null);
			nameField.setText(Util.EMPTY_STRING);
			emailField.setText(Util.EMPTY_STRING);
			phoneField.setText(Util.EMPTY_STRING);
			postageField.setText(Util.EMPTY_STRING);
			trackingIdField.setText(Util.EMPTY_STRING);
			addressField.setValue(Util.EMPTY_STRING);
		}
		
	}
}
